package com.shux.usermanager.biz.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.druid.util.StringUtils;
import com.shux.common.exception.ShuxRunTimeException;
import com.shux.common.token.ShuxUsernamePasswordToken;
import com.shux.usermanager.biz.ILoginBiz;
import com.shux.usermanager.biz.ISysMenuBiz;
import com.shux.usermanager.biz.ISysUserBiz;
import com.shux.usermanager.entity.SysMenu;
import com.shux.usermanager.entity.SysRole;
import com.shux.usermanager.entity.SysUser;
import com.shux.utils.constants.Constant;
import com.shux.utils.other.AppUtil;
import com.shux.utils.other.Jurisdiction;
import com.shux.utils.other.Tools;
import com.shux.utils.page.PageData;
import com.shux.utils.string.StringUtil;

/**
 **********************************************
 *  描述：登录验证
 * Simba.Hua
 * 2017年5月30日
 **********************************************
**/
@Service("loginBiz")
public class LoginBizImpl implements ILoginBiz{
    
    private Logger logger = LoggerFactory.getLogger(getClass());
    private @Autowired ISysUserBiz sysUserBiz;
    private @Autowired ISysMenuBiz sysMenuBiz;
    @Override
    public Object toLogin(HttpServletRequest request) {
        if (request == null)
            return null;
        String param = request.getParameter("KEYDATA");
        if (StringUtil.isEmpty(param))
            return null;
        String[] keydata = param.replaceAll("usershuxlogin", "").replaceAll("autosimba", "").split(",shux,");
        if (keydata.length == 3) {
            String username = keydata[0];//
            String password = keydata[1];//
            String pageSecturityCode = keydata[2];
            //把验证码、用户名、密码交给shiro校验
            checkSecurityCode(pageSecturityCode);
            Subject subject = SecurityUtils.getSubject();
            //把验证码、用户名、密码交给shiro校验
            ShuxUsernamePasswordToken token = new ShuxUsernamePasswordToken(username, password,pageSecturityCode);
            subject.login(token);
        } else {
            throw new ShuxRunTimeException("缺少用户名或密码或验证码");
        }
        Map<String, String> map = new HashMap<String, String>();
        map.put("result", "success");
        if(WebUtils.getSavedRequest(request) == null){
            map.put("redirect", "main/index");
        }else{
            String preUrl =  WebUtils.getSavedRequest(request).getRequestURI();
            if(StringUtils.isEmpty(preUrl)){
                map.put("redirect", "main/index");
            }else{
                map.put("redirect",preUrl);
            }
        }
       
        return AppUtil.returnObject(new PageData(), map);
    }
    
    @Override
    public ModelAndView toLogin2(HttpServletRequest request) {
        String username = request.getParameter("username");//
        String password = request.getParameter("password");//
        String code = request.getParameter("code");
        checkSecurityCode(code);
        Subject subject = SecurityUtils.getSubject();
        //把验证码、用户名、密码交给shiro校验
        ShuxUsernamePasswordToken token = new ShuxUsernamePasswordToken(username, password,code);
        subject.login(token);
        /*String exceptionClassName = (String) request.getAttribute("shiroLoginFailure");
        //根据shiro返回的异常类路径判断，抛出指定异常信息
        if(exceptionClassName!=null){
          if (UnknownAccountException.class.getName().equals(exceptionClassName)) {
            //最终会抛给异常处理器
            throw new ShuxRunTimeException("账号不存在");
          } else if (IncorrectCredentialsException.class.getName().equals(
              exceptionClassName)) {
            throw new ShuxRunTimeException("用户名/密码错误");
          } else if(UserConstant.RANDOM_CODE_ERROR.equals(exceptionClassName)){
            throw new ShuxRunTimeException("验证码错误 ");
          }else if(UserConstant.SESSION_CODE_ISNULL.equals(exceptionClassName)){
              return new ModelAndView("redirect:/usermanager/login");
          }else {
            throw new ShuxRunTimeException("未知错误 ");//最终在异常处理器生成未知错误
          }
        }*/
        if(WebUtils.getSavedRequest(request) == null){
            return new ModelAndView("redirect:usermanager/main/index");
        }else{
            String preUrl =  WebUtils.getSavedRequest(request).getRequestURI();
            if(StringUtils.isEmpty(preUrl)){
                return new ModelAndView("redirect:usermanager/main/index");
            }else{
                return new ModelAndView("redirect:"+preUrl);
            }
        }
       
        
    }
    
    private void checkSecurityCode(String pageCode){
        Session session = Jurisdiction.getSession();
        String sessionSecurityCode = (String)session.getAttribute(Constant.SESSION_SECURITY_CODE);
        if(StringUtil.isEmpty(sessionSecurityCode)){
            throw new ShuxRunTimeException("验证码已经失效！");
        }
        if(!sessionSecurityCode.equalsIgnoreCase(pageCode)){
            throw new ShuxRunTimeException("验证码不正确！");
        }
    }
    
    public ModelAndView mainIndex(String changeMenu,HttpServletRequest request){
        ModelAndView mv = new ModelAndView();
        try {
          Session session = Jurisdiction.getSession();
          Subject subject = SecurityUtils.getSubject();
          SysUser user = (SysUser) subject.getPrincipal(); // 读取session中的用户信息(单独用户信息)
          if (user != null) {
              SysUser userr = (SysUser) session.getAttribute(Constant.SESSION_USERROL); // 读取session中的用户信息(含角色信息)
            if (null == userr) {
              user = sysUserBiz.getUserAndRoleById(user.getUserId()); // 通过用户ID读取用户信息和角色信息
              session.setAttribute(Constant.SESSION_USERROL, user); // 存入session
            } else {
              user = userr;
            }
            String username = user.getUsername();
            SysRole role = user.getRole(); // 获取用户角色
            String roleRights = role != null ? role.getRights() : ""; // 角色权限(菜单权限)
            session.setAttribute(StringUtil.join(username,Constant.SESSION_ROLE_RIGHTS),roleRights); // 将角色权限存入session
            session.setAttribute(Constant.SESSION_USERNAME, username); // 放入用户名到session
            //获取用户所拥有的权限
            List<SysMenu> allmenuList = getAllMenuList(username,roleRights);
            // 切换菜单处理=====start
            List<SysMenu> menuList = changeMenu(username, allmenuList,changeMenu);
            // 切换菜单处理=====end
//            if (null == session.getAttribute(StringUtil.join(username, Constant.SESSION_QX))) {
//              session.setAttribute(StringUtil.join(username, Constant.SESSION_QX),sysUserBiz.queryUserButtonAuth(username)); // 按钮权限放到session中
//            }
            sysUserBiz.updateUserIp(user.getUserId(),request); // 更新登录IP
            mv.setViewName("/usermanager/jsp/index/main");
            mv.addObject("user", user);
            mv.addObject("menuList", menuList);
          } else {
              return new ModelAndView("redirect:/usermanager/login");
           // mv.setViewName("usermanager/jsp/index/login");// session失效后跳转登录页面
          }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return new ModelAndView("redirect:/usermanager/login");
          
        }
      return mv;
    }
    /**
     * 
     * @param allmenuList
     * @param username
     * @param roleRights
     */
    private List<SysMenu>  getAllMenuList(String username,String roleRights){
        List<SysMenu> allmenuList = new ArrayList<SysMenu>();
        Session session = Jurisdiction.getSession();
        if (null == session.getAttribute(StringUtil.join(username,Constant.SESSION_allmenuList))) {
            allmenuList = sysMenuBiz.queryMenusRoot();// 获取所有菜单
            if (Tools.notEmpty(roleRights)) {
              allmenuList = sysMenuBiz.checkMenu(allmenuList, roleRights); // 根据角色权限获取本权限的菜单列表
            }
            session.setAttribute(StringUtil.join(username,Constant.SESSION_allmenuList),allmenuList);// 菜单权限放入session中
          } else {
            allmenuList = (List<SysMenu>) session.getAttribute(StringUtil.join(username,Constant.SESSION_allmenuList));
          }
        return allmenuList;
    }
    /**
     * 
     * @param menuList
     * @param username
     * @param allmenuList
     * @param changeMenu
     */
    private List<SysMenu> changeMenu(String username,  List<SysMenu> allmenuList,String changeMenu){
        List<SysMenu> menuList = new ArrayList<SysMenu>();
        Session session = Jurisdiction.getSession();
        if (null == session.getAttribute(StringUtil.join(username,Constant.SESSION_menuList))|| ("yes".equals(changeMenu))) {
            List<SysMenu> menuList1 = new ArrayList<SysMenu>();
            List<SysMenu> menuList2 = new ArrayList<SysMenu>();
            // 拆分菜单
            allmenuList.forEach((menu)->{
                if("1".equals(menu.getMenuType())){
                    menuList1.add(menu);
                }else{
                    menuList2.add(menu);
                }
            });
            session.removeAttribute(StringUtil.join(username,Constant.SESSION_allmenuList));
            if ("2".equals(session.getAttribute("changeMenu"))) {
              session.setAttribute(StringUtil.join(username,Constant.SESSION_menuList),menuList1);
              session.removeAttribute("changeMenu");
              session.setAttribute("changeMenu", "1");
              menuList = menuList1;
            } else {
              session.setAttribute(StringUtil.join(username,Constant.SESSION_menuList),menuList2);
              session.removeAttribute("changeMenu");
              session.setAttribute("changeMenu", "2");
              menuList = menuList2;
            }
          } else {
            menuList = (List<SysMenu>) session.getAttribute(StringUtil.join(username,Constant.SESSION_menuList));
          }
        return menuList;
    }
    
    

}
